- web6047 - (2021/09/10(金) 現在、システム調整中のため、一部の表示がおかしいかもしれません)



*** これ↑は、1987年 日本ファルコム発売の PC-8801mkIISR 用 ARPG「ソーサリアン」のタイトルのパロディです ***

web6047 2020 7

プログラミングやRPG(作るほう)が好きな人の日記


このホームページは毎日 夜11時にアクセスできなくなります。

朝6時半に再開されます。(世の中のネット依存対策として)

NO PC WEEK に代わる PC 使用制限のしくみ(β版)
No. (ついでに
勉強1問)
PC使用
開始時刻
予定使用時間 時間:分
(当日限度時間 時間:分)
予定終了時刻 実際終了時刻 実際使用時間 時間:分
(当日限度時間 時間:分)
オーバー理由
判定 作業内容
137 19:00 3:00(3:00) 22:00 22:56 3:56(3:00)
あるJavaScriptがうまくいかず、執着した
× トップページ
136 19:10 1:30(1:30) 20:40 20:39 1:29(1:30) RPG試作
135 18:40 1:30(1:30) 20:10 20:31 1:51(1:30) RPG試作
134 18:50 1:30(1:30) 20:20 20:30 1:40(1:30) RPG試作
133 20:45 1:00(4:00) 21:45 21:59 1:14(4:00) RPG試作
132 17:50 1:30(4:00) 19:20 19:24 1:34(4:00) RPG試作
131 11:35 1:30(4:00) 13:05 13:09 1:34(4:00) RPG試作
130 × 15:30 2:30(4:00) 18:00 18:36 3:06(4:00)
やはり、プログラム以外の「記事」とかだと、
決めた時間に終わらせる気持ちが薄いようだ。
× RPG試作について記事
129 10:30 1:30(4:00) 12:00 12:17 1:47(4:00) RPG試作について記事
128 20:15 2:00(4:00) 22:15 22:55 2:40(4:00)
いけね、時間間違えちった…
× RPG試作
127 15:55 2:00(4:00) 17:55 18:08 2:13(4:00) RPG試作



1:30(4:00)



(1:30使用せず)
126 20:10 1:30(4:00) 21:40 21:56 1:46(4:00) RPG試作
125 18:15 1:00(4:00) 19:15 19:14 0:59(4:00) 秀丸マクロ作成



1:30(3:00)



(1:30使用せず)
124 20:35 1:30(3:00) 22:05 22:13 1:38(3:00) RPG試作
123 20:35 0:30(2:00) 21:05 21:20 0:45(2:00) RPG試作/モデリング
122 16:20 1:30(2:00) 17:50 18:00 1:40(2:00) RPG試作/モデリング
121 18:30 1:30(1:30) 20:00 20:10 1:30(1:30) RPG試作
120 20:30 1:00(3:00) 21:30 22:02 1:32(3:00)
ちょっと進めたかった…
RPG試作
119 18:25 1:00(3:00) 19:25 19:35 1:10(3:00) RPG試作/モデリング
118 14:10 1:00(3:00) 15:10 15:15 1:05(3:00) RPG試作/モデリング
117 20:24 1:30(4:00) 21:54 22:05 1:41(4:00) RPG試作
116 16:25 0:30(4:00) 16:55 16:55 0:30(4:00) RPG試作
115 12:30 2:00(4:00) 14:30 14:33 2:03(4:00) RPG試作
114 12:05 1:00(4:00) 13:05 18:53
5:48(4:00)
プログラム以外の「記事」とかだと、
決めた時間に終わらせる気持ちが薄い
×
今月の扉について記事
113 22:45 1:00(4:00) 23:45 23:46 1:01(4:00) RPG試作
112 21:25 0:30(4:00) 21:55 21:57 0:32(4:00) RPG試作
111 16:05 1:30(4:00) 17:35 17:45 1:40(4:00) RPG試作
110 × 1:00(4:00) × 14:45 何気なく始めて時間がかかった × 歯磨き物語.bat作成
109 23:50 1:00(2:00) 24:50 24:57 1:07(2:00) RPG試作
108 21:10
1:00(2:00)
22:10
22:22
1:12(2:00)

RPG試作
107 19:15 1:30(1:30) 20:45 20:53 1:38(1:30) RPG試作
106 20:50 1:30(1:30) 22:20 22:17 1:27(1:30) RPG試作
105 21:30 1:00(4:00) 22:30 22:32 1:02(4:00) RPG試作
104 17:40 1:30(4:00) 19:10 19:20 1:30(4:00) RPG試作
103 12:45 1:30(4:00) 14:15 14:27 1:42(4:00) RPG試作



1:00(3:00)



(1時間使用せず)
102 22:55 1:00(3:00) 23:55 0:06 1:11(3:00) RPG試作
101 19:40 1:00(3:00) 20:40 20:47 1:07(3:00) RPG試作
100 19:10 1:00(2:00) 20:10 ×
スクリプトを完成させようと思った × 7月の扉スクリプト(完)
99
12:50 1:00(2:00) 13:50 ×
気がゆるんで、長く続けた
×
aboutThisWebsite
98 23:15 1:00(2:00) 0:15 0:30 1:15(2:00) 7月の扉スクリプト
97 20:25 1:00(2:00) 21:25 21:31 1:06(2:00) 7月の扉スクリプト
96 18:25 1:30(1:30) 19:55 20:07 1:42(1:30) 7月の扉スクリプト
95 23:20 0:30(0:30) 23:50 23:55 0:35(0:30) 7月の扉スクリプト
94 15:25 1:30(4:00) 16:55 17:09 1:44(4:00) 7月の扉スクリプト
93 13:10 1:30(4:00) 14:40 14:44 1:34(4:00) 7月の扉スクリプト
92
9:30 1:00(4:00) 10:30 10:20 0:50(4:00) iTunesと画像表示の連携

この表の意図:

多くの人はパソコンのやりすぎやネットゲームのやりすぎには困っていると思います。

参考に言うと、この表を使う前の私は 1 回の PC 使用時間がノンストップで 17 時間というときもあったし、平均で言うと毎日 9 時間はやっていたと思います。

そういう徹夜とか長時間作業をするよりも、昼間の短時間作業のほうが生産性は高いのでは? と数年前から考えてきました。

パソコンの使用時間を事前に決めてネット上に公開することで、パソコンのやりすぎを防止できるかどうかこの表を使って試しています。


記入の法則:

  • 日付は表示していません。しかし、白と灰色の色分けは、同じ色の連続で同じ日を表しています。
  • 左端の「(ついでに勉強1問)」について
    この表の目的とは異なりますが、ついでとして、遊び100%の毎日を送るときでも勉強の習慣を忘れないために、たった1問で良いので解くことにします。
    正直言うと毎回遊ぶ前に必ず1問勉強するのは心が折れそうです。でも慣れさえすれば…と思います。追記:やってみると結構効果的で役立っています。
    行ったら◎、行わなかったら× を記入。
  • 右端の「判定」について
    予定使用時間と実際使用時間を比べて
    ◎ 9分以下
    ○ 10分~19分
    △ 20分~29分
    × 30分以上


例外:

  • 「実際終了時刻」のあと、プログラミングの場合のみスッパリ終了しないで、今後のプログラミングの方針をテキストファイルに書くのは OK にしています。
  • 自分のホームページやプログラムを読んでいて誤字脱字を発見した際、その「修正」は訪問者にとっても管理人にとっても有益なので、「タイマーで測って10分未満。1点修正したら終了」を条件に作業してよい。また、基本的にそれを連続させないこと。


中途結果:

結構いい結果になっています。炊事や掃除、散歩、早起きなどが好ましいリズムでできるようになりました。




2020/7/26(日)

RPG試作 -[rpg]

前日の最後に紹介した「パレット」という方法で RPG の「コマンドウィンドウ」システムを作り始めましたが、なかなか手応えが良いような…


メモと同じようにプログラムされています。

2020年8月7日追記:あれっ…しばらくしてからこのコード見たけど、自分でも意味わかんないわ…なんだったっけな…これ… pal とか pals とかパレットだとか、一般的ではない真新しいものを取り入れても、どうかなってことですね。

▼「パレット」メモ

▼実行画面

プログラムリスト

(2020年8月7日追記:リンク切れしていたのを直しました…)

 この画像は「イラストAC」の無料素材です。

この試作がうまくいってくれるとありがたいんですが。。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/25(土)

RPG試作 -[rpg]

私が最近取り組んでいる「RPG試作」について簡単に紹介します。

RPG というものは他のシューティングゲームやアクションゲーム、パズルゲームと違って、システムが複雑で膨大になる感じがしています。

私は小学生、中学生、高校生と、ずっと RPG開発 に取り組んできましたが、今思えば、ドンキホーテのように勝てない相手に向かっていたんだと思います。

結構難しい しくみが多く、子供~少年には無理なんじゃないかと思います。(シンプルで拡張性もあるプログラムは子供には難しい)

でも年を取った私も、今では体力がなくなって、最終的な完成版の RPG に到達するには、先の道のりがだいぶ遠い気がしています。


これまで作ってきた試作品 6 点を掲載します。

どの試作もわかりづらいもので、RPG自作 に興味がある皆さんの役にはあまり立たないと思いますが、「管理人はこういうことをやっている」程度にご覧ください。

(ゲームとして遊べるものはなく、すべて「ウィンドウ入力」の試作品です)


fig.
▲JavaScriptでシナリオイベントを実現する

1. ウィンドウ入力 試作1 (.../20200621-1/simple.html)

概要:

  • JavaScript で「シナリオイベント」や「戦闘ロジック」を実現するサンプルです。

プログラムリスト



fig.
▲RPGのウィンドウを模索している

2. ウィンドウ入力 試作2 (.../20200621-ドラクエの.../simple2.html)

概要:

  • メッセージを1文字ずつ表示。
  • controls というオブジェクトに各ウィンドウをまとめて、制御しようとしている。
  • 戦闘コマンドを各キャラ、順次入力させるのに、wizard という考え方を使っている。
    wizard = [
        キャラ1の戦闘コマンド入力,
        キャラ2の戦闘コマンド入力,
        キャラ3の戦闘コマンド入力,
    ]
    それぞれ入力が終わったら次のキャラへ処理を移す、というもの。

プログラムリスト



fig.
▲戦闘のコマンド入力のみ

3. ウィンドウ入力 試作3 (.../20200627-クラスを使用/simple3.html)

概要:

  • クラス宣言に prototype ではなく、class を使うようにした。
  • extends で、より基本的なクラスから順次継承していけるようになった。
  • サブメニューをどうプログラムするかで悩んでいる。
    Menu クラスの keytype メソッド内でサブメニューについて書いている。

プログラムリスト



fig.
▲戦闘とフィールドコマンドの2種あり

4. ウィンドウ入力 試作4 (.../20200629-メモにまとめた.../simple4.html)

もとになったメモ:

このメモ書き  を動機にして作り始めた試作です。

メモ書きの言わんとすることは、

  • 戦闘でキャラの入力を順次実行するには、Wizard(意味:アプリケーションソフトの設定や操作などを、対話形式で行うことにより容易にする機能)に似た方法を使ってできるのでは。
  • Menu はシナリオイベントの中で「入力ツール」として機能する。独立した状態で機能を果たすだけのもので、どこか癒着したようなプログラムにしない。
  • フィールド上のコマンドメニューも項目が1つのWizである。

概要:

  • サブメニューをどうプログラムするかで悩んでいる。
    Menu クラスの keytype メソッド内でサブメニューについて書いている。
    フィールド上でのコマンドで、「どうぐ>だれの?」を入力したあと、次のサブメニューの内容を、前の入力の「だれの?」で選んだキャラのどうぐリストにする必要がある。
    いろいろ方法があるが、この試作では、
    【通常のメニュー】
    subMenu : {
        title : "サブメニュー",
        items : [  //配列
            項目1,
            項目2,
            項目3,
        ]

    }
    【メニューで選んだ項目が次のメニューの項目になる場合】
    subMenu : {
        title : "だれの?",
        items : {  //オブジェクト
            items1 : キャラ配列(だれの?のメニュー項目になる),
            items2 : 選んだキャラの「どうぐ」のメニューを開かせる何らかの情報,
        }

    }
    items を見て、配列かオブジェクトで処理を変える。
    オブジェクトの場合は、そのメニューで決定した項目を使って次のメニューを作成する。
    このやり方が良いやり方だとは思えない…
    (この問題を問題Aとする)

プログラムリスト



***

最近の若者だったら、こんなサブメニューなんて「これでいいでしょ」と言って簡単に作ってしまい、その内容を私が見て「ああ、たしかにそれでいいわ…」、、なんて状況を想像してしまいます。

それとも私が取り組んでいるこの「サブメニュー」というのは実際に難しいものなんでしょうか。

ドラゴンクエスト1~4の同じコマンドメニューは結構よくできています。どんなプログラムになっているのか、そのプログラマーはどんな様子でそれを作っていたのか…、などなどいろいろ想像しています。

***


fig.
▲ウィンドウについて作り込んだ

5. ウィンドウ入力 試作8 (.../20200703-新しいメモ/simple8.html)

もとになったメモ:

メモ書き1 

このメモ書きの言わんとすることは、

  • コマンドメニューがやっていることは、MS-DOSなどのコマンドラインと似ている。
    そのつもりで作れば、うまくまとまるのでは?

メモ書き2

このメモ書きの言わんとすることは、

  • コマンドラインではなく、JavaScript の DOM(データオブジェクトモデル)の書式に合わせたほうがいい。

これらメモ書きを動機にして作り始めた試作ですが、メモの内容は後回しにして、いろいろなタイプのウィンドウを作り込んでいます。

概要:

  • 思い切って、ウィンドウのシステムを「シナリオイベント」中に書き込んでみた。
    シナリオイベント中に書かれる、app.selectMenu() 内に、ウィンドウ作成やサブメニューのプログラムを書いた。
  • サブメニューをどうプログラムするかで悩んでいる。(問題A)
    この試作では、メニュー項目が選ばれたとき、onselect という関数を呼ぶようにして、そのなかで、
    local.nextMenu.items = 選んだキャラのどうぐリスト
    のようにして、次のメニューの項目配列を書き換えている。
    しかし、このやり方も良いやり方だとは思えない…

プログラムリスト



fig.
▲コンテキスト(文脈)でサブメニュー

6. ウィンドウ入力 試作9 (.../20200724-新しいメモ2/simple.html)

もとになったメモ1:

メモ書き1 

このメモ書きの言わんとすることは、

  • ウィンドウやメニューについて必要なことの洗い出し。
    • サブメニューを表示できること。
    • 選んだ項目によって次メニューを更新できること。
    • やくそうを選んだ場合、状況によってサブメニューを変えられること。
    • カーソルを動かしながら、べつのウィンドウの内容を変えられること。
      たとえば、ドラクエの「つよさ」でキャラの名前を選ぶ毎につよさのウィンドウが変わる等。
  • メモの下部右側については、メニューのシステムをごく単純なしくみにして、再帰的に運用できないか検討した。

もとになったメモ2:

メモ書き2

このメモ書きの言わんとすることは、

  • 上記メモ書きの要約。「サブメニュー」を作ることができ、「動的更新」と「場合分け」ができる。それだけが(とりあえず)必要だ。それぞれ、bridge と context と名付けました。

概要:

  • サブメニューの開き方を3種類に増やした。
    1. 「bridge」という付与情報(以前話題にした chainTo の名前を変えたもの)を設けて、問題Aを解決する。
    2. 「直」。メニューの定義に当たり前のようにサブメニュー情報を配置したもの。
      この場合は問題Aを解決できない(メニューで選んだ内容をもとにしてメニュー作成できない)
    3. 問題Aとは別の新たな問題を解決するもの。
      フィールド上のコマンドで「どうぐ」「だれの?」「やくそう」を選んだときはさらに、
       どうする?
       つかう
       わたす
       すてる
      というサブメニューが表示されるが、
      戦闘時のコマンドで「どうぐ」「やくそう」を選んだ時は、やくそうを選んだ時点で暗黙で「つかう」となり、次のキャラのコマンド入力に移る。
      というように、同じやくそうでも状況によってサブメニューの有無や内容が変わる場合がある。
      今回の試作では、どんなメニューを選んできたかを history に記録を取り、その history のうち、有効なものを context として取り上げる。
      たとえば、「やくそう」という道具に "キャンプ" と名付けられたサブメニューデータと、"戦闘"と名付けられたサブメニューデータ、つまりサブメニューデータが複数用意されているとして、history が [ キャンプ, どうぐ, C1 ] となっていた場合、この history のうち、「やくそう」のデータに用意があるもの(有効なもの)は「キャンプ」なので、context は「キャンプ」となる。
      次に表示するサブメニューは やくそうデータ[ "キャンプ" ] となり、状況によりサブメニューを選ぶことができる。
      (…日本語は苦手だ…)

プログラムリスト



試作を重ねたけど納得いかず、まだ続く…

…で、

これら試作を重ねてきましたが、それでも納得できません。

そのゲーム専用にゴリゴリ作って進むなら、こんなに悩みませんが、万能のシンプルの汎用の…といった「ザ・コマンドメニュー」みたいなものを作りたいので…。

描いて描いて描きまくるというような、絵描きがひたすら描いてはクシャクシャポイするみたいだなと、いろいろ作っていて思いました。

または漫画家が何度も原稿を描いては編集者に上げるんだけど、編集者はことごとく「面白くない」と言ってボツにするみたいな感じ。それを、一人でやってるみたいな。

でも望みは断たれていません。


最後に、新しい方法として「パレット」と名付けた方法を考えてみます。

このメモ書きの言わんとすることは、

今までの試作はオブジェクト指向になっていて、サブメニューのしくみも難しい感じでした。

もっと、

…にしないと、と思って考えた方法で、これから試作するところです。

まったく新しい方法なので、楽しみです。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/22(水)

間違い訂正 -[javascript]

2020/7/17(金)の日記で「JavaScript のクラス定義では super() は使えるけど、super.method() は使えない」と書きましたが、それは間違いで、super.method() は使えるようです。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/18(土)

RPG試作 スクリーンショットと、謎の言葉「INTKSBFS」 -[rpg]

RPG試作 スクリーンショット

ちょっと面白いかなと思って。

現在、内側のプログラムの流れを作っているので見た目はしょぼいですが…。

 

ドラクエっぽいですが、最終的にはドラクエと違うデザインにしようと思っています。

できること:

それらが、個人的なプログラムではなく、初心者の方が参考にできるプログラムになるよう気を付けているところがポイントです。


謎の言葉「INTKSBFS」

そのほか面白いものとしてこういうものもあります。

I・N・T・K・S・B・F・S

これは、私が日々 RPG を研究する中で考え出したもので、「面白い RPG を作るために抑えておくべき項目」の頭文字を並べたものです。

この項目を抑えればその RPG は面白く、成功する。というものです。


INTKSBFS をローテーションして 1 日 1 項目で順次考えるようにすると、それぞれについて まんべんなく、アイデアを出し深く掘り下げることができます。

「アイエヌテー、ケーエスビーエフエス」と。

職場の「5S」みたいですね。「整理整頓清掃清潔しつけ」

面白いですかね?面白くない?


(訪問者のどんなニーズと この記事がつながるか)


2020/7/17(金)

今月の扉コンテンツ -[javascript]

毎月、私のこの Web ページではトップページの冒頭で自作の JavaScript プログラムやイラストを飾っています。

今月は、1987 年に発売された日本ファルコムのARPG 「ソーサリアン」のタイトル画面のパロディです。JavaScript で作成しました。

背景には星が降り注ぎ、テキストが 2 画面分表示されたあと、きらびやか なタイトルが大きく表示されます。

オリジナル(パロディした元製品)の動画は下のリンクで見られます。

キーワード「ソーサリアン PC-98 オープニング」で動画を検索(Bing)


パロディを作っていて感じた 日本ファルコムの芸術性

今回、オリジナルを細かいところまで再現する作業をしていて、他のゲームメーカーには見られなかったような芸術性に気づきました。

芸術性というか、「繊細」、「が良い」、「センスが良い」というのかな…

そう感じたのは、テキストがじわじわと表示されるところを再現(プログラミング)しているときでした。


テキストは、[ 表示なし → だんだん青 → だんだん明るい色 → だんだん青 → だんだん表示なし ] という移り変わりで表示されます。

【移り変わり確認ツール】
▼テキストがじわじわ表示されるところ

0 / 8.1 sec.

  1. だんだん青が表示される
  2. だんだん明るい色になる
  3. 待ち(3秒。ゆっくりだと15秒)
  4. だんだん青くなる
  5. だんだん消える

再生  ゆっくり再生  一コマ戻す  一コマ進める  最初にもどる  


現在のコンピューターは 1677 万色以上表示できるので普通に なめらかにフェードイン/フェードアウトできますが、当時のコンピューター(PC-9801の古いもの)は表示色数が 8 色しかなかったので、「青を経由して本来の色を表示する」という工夫がよく行われていました。

たとえば、ファミコン版ドラゴンクエストなどでもフィールドから街に入るときなどは、

[ フィールドの明るい色 → 青 → 黒画面 → 青 → 街の明るい色 ]

という色変更でフェードイン/フェードアウトを再現しています。


今回のソーサリアンでは、「色変更」だけではなく「ドット操作」による「だんだん青」という表現が加えられています。

もちろんドラゴンクエストはファミコンなので処理速度の関係でドット操作できず、色を変えるだけになっていたのかもしれません。

真偽のほどはわかりませんが、ファルコムの「だんだん青」というひと手間を加えているところに他とは違う芸術性みたいなものを感じました。

限られた性能(表示式数8色等)のなかでアイデアと工夫によって何かを実現しようという確かな努力が、プレイヤーの心に訴えるところがあるんだと思います。

また、その工夫による「青を経由する」という技法が、高性能のフェードイン/フェードアウトにはない、特別で個性的な表現を作り出してもいます。

高性能だから高性能のままに なめらかなフェードイン/フェードアウトにするのではなく、その時、その場所に合うのであれば、「青を経由する」という過去に登場した技法を検討するというのも、良いことではないかと思います。

「普通にオープニングを見てゲームを遊ぶだけ」では気づきませんでしたが、今回のパロディを作るという作業によって、ファルコムが本当の意味で優位に立っていたことを垣間見ることができました。


JavaScript

このパロディ プログラムの説明です。

今までクラス定義はこの方法を使っていました。

function TestClass() {
    //constructor
    ...
}
TestClass.prototype.testMethod = function() {
    ...
}


しかし、今回は Java とよく似た方法を使いました。

TestClass {
    constructor() {
        ...
    }
    testMethod() {
        ...
    }
}

constructor() のなかで、super() は使えますが、メソッドの中で super.method() が使えないので(下記の追記参照)、extends でクラスの継承を行うときは、スーパークラス(継承元)のメソッドの内容を手動でコピーしなきゃなりません。

2020年7月22日追記: super.method() 使えますね。間違えていました。(どこかのサイトで使えないみたいなことが書いてあった…昔の話かな)

でもそういうことも将来解決されちゃうと、JavaScript はどんどん Java そのものになっていきそうです。


プログラムリストは index.js です。

おてもとで動かすためのファイル一式はこちらです。↓

FILE DOWNLOAD
おてもとで実行できるようにと思ってファイル一式をzipにしましたが、htmlファイルをクリックしてブラウザに開かせると、「Loading..」と表示したまま動かず、shift+ctrl+J でコンソールを見ると
SecurityError: The operation is insecure.
というエラーが出ています。
直接開くのではなく、Webサーバー経由で開けば同エラーは出ません。
お手軽なWebサーバーの立て方
難しいとは思いますが、こちらのサイトさんの「Chrome アプリ編」を参考にしてWebサーバーを立ち上げてみてください。そのアプリの設定画面のフォルダの指定で、zipを展開してできたフォルダを選び、表示されるURLにアクセスしてみてください。ページ上の simple.html をクリックすれば動くと思います。
202007-indexJS.zip
432 KB
DOWNLOAD
公開 2020/7/17


index.js は全部で 438 行あります。

定義しているクラスは、App、TestImage の2つです。

クラス App のメソッドは execute、fadeImage、frame、draw、delay、loadImage、start、stop、onscrollx の 9 つです。

クラス TestImage のメソッドは draw の1つです。

HTML の onload などで、app = new App(..) とすれば、プログラムが実行されます。


(※下記は少し難しい内容です)

プログラムの流れをおおまかに説明します。

new App() で App のインスタンス(下記用語)が作成されるとき、そのコンストラクタ(下記用語)内でイベントハンドラ関数(下記用語) onscrollx がイベントではなく手動で呼ばれ、その中でメソッド(下記用語) start が呼ばれ、その中で setInterval が呼ばれます。

test() {
    app = new App();    //インスタンス作成
}
class App {
    constructor() {
        ...
        this.onscrollx();    //イベントハンドラ関数を手動で呼ぶ
        this.execute();
    }
    onscrollx() {
        ...
        this.start();
        ...
    }
    start() {
        ...
        setInterval( this.frame, 100 );    //アニメの1コマを実行
        ...
    }
    frame() {
        //背景の星を動かす
        ...
        //汎用的なアニメ処理
        ...
    }
    execute() {
        //背景の星のオブジェクトを 50 個生成
        ...
        //画像のプリロード
        ...
        //各種アニメを順次実行
        ...
    }
}

このプログラムは setInterval でアニメの1コマを実行しています。

setInterval は、メソッド frame を呼びます。frame は具体的に背景の星を動かすほか、「汎用的なアニメ処理」を行っています。

用語:

インスタンス: クラスという「設計図」から作られた「実物」

コンストラクタ: new App() されたときに実行される関数

イベントハンドラ関数: 例えばボタンが押されたら実行されるとか、何かが起こったら実行されるという関数

メソッド: そこにヒモづいた関数


コンストラクタ内で手動でイベントハンドラ関数 onscrollx が呼ばれた後、メソッド execute が呼ばれます。

execute では背景の星のオブジェクトが 50 個生成されるほか、画像のプリロード、そして各種アニメが順次実行されます。


この「各種アニメが順次実行される」という動きは、 async, await, Promise などを使って実現しています。async, await, Promise は理解するのが少し難しいですが、これからおおまかに ゆるゆる で説明してみます。

次のプログラムは、関数 test を一時停止(await)して、別のことを行い(Promise)それが終わったら test を再開するプログラムです。

async function test() {
    ...
    await delay( 3000 );    //ここで一時停止して、
    ...
}
function delay( ms ) {
    return new Promise( function( tellOk ) {
        setTimeout( tellOk, ms );    //setTimeoutで ms 秒後に tellOk() を実行して「処理終了」を知らせると、delay の次行へ戻る。
    } );
}

システムがイベント発生時に event オブジェクトを引数にしてイベントハンドラ関数を自動的に呼ぶのと同じように、

Promise が tellOk 関数を引数にして(Promiseの引数となっている)関数を自動的に呼びます。

event オブジェクトがプログラマーが作るのではなく、システムが作るのと同じように、

tellOk はプログラマーが作るのではなく、Promise が作るものです。その辺 混乱しないように…。

ここではわかりやすく tellOk (意味:Okと伝えなさい)と名付けていますが、一般的には resolve (意味:解決する)と呼ばれています。resolve は中学校の英語で習わなかったので意味がちょっとわかりませんが、tell ok ならわかるでしょう。

ちょっと余談ですが、この tellOk と名付ける前は Apple の Webサイトで初めて iMac を紹介したときのキャッチフレーズ「Say hello to iMac」みたいに「sayOkToPromise」にしようかとかいろいろ考えていました。

ホントに余談ですね。話は戻り、

↓同じことを async, await, Promise を使わないで実現することはたぶんできないのではと思います。

//×
function test() {
    ...
    delay( 3000 );
    ...
}

function delay( ms ) {
    //どう書く? ここで setTimeout すると処理はすぐに delay の次行を実行してしまうし、
    //setTimeout で delay の次行にピンポイントで戻ることもできない…
}

↓async, await, Promise を使う他の例として、何かキーが押されたら次の行へ という場合は、

async function test() {
    ...
    await hitAnyKey();    //ここで一時停止して、
    ...
}
function hitAnyKey( ms ) {
    return new Promise( function( tellOk ) {
        window.onkeydown = function( e ) {
            tellOk();    //キーダウンイベントにて、tellOk() で「処理終了」を知らせると、
                         //hitAnyKey の次行へ戻る。
        }
    } );
}

↑ゲームでよく使う - HIT ANY KEY - というくだり がこうやって実現できるのはうれしいですね。

↓今回のアニメ処理の場合は、

async execute() {
    ...
    await this.fadeImage( .. );    //1つのアニメを開始
    ...
}
fadeImage( .. ) {
    return new Promise( function( tellOk ) {
        //1つのアニメを定義し、配列 anms へ入れる。
        anm = {
            ...
            tellOk : tellOk,    //anm.tellOk は(この関数の引数の)tellOk という意味
        }
        this.anms.push( anm );
    }
}
frame() {    //frame は setInterval によりいつでも定期的に実行されている。
             //配列 anms に anm が入ってくると1つのアニメとして処理する。
    for( anms の各要素 anm ) {
        あるオブジェクトが持つ1つの値を増減させるような記述をここに書いている。
        (drawでそのオブジェクトを描けばアニメになる)
        その値が目的の値に到達したら、1つのアニメ終了。anm.tellOk() を行う。
        すると、execute の await の次行へ戻る。
    }
}

こうやってメソッド execute の中の各アニメがひとつひとつ順次実行されるわけです。

ちょっとわかりにくいところがあったかな…。


そのほか今回のプログラムでは async, await, Promise を使って、

といったことも行っています。

「await で処理を止めて…」と、まるで await 単体で処理が止まるかのような言い方をしていますが、正しくは、

「await 演算子が付いた関数は、Promise が返されるまで待機する」

です。

await を使うときはその上の関数に async を付けます。付けないと「await は使えない」というエラーになります。

(以上、少し難しい内容でした)


最後に、パロディが著作権としてどれくらい許されているのかについては当サイトの「パロディ作品(自作)の掲載の考え方」をご覧ください。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/16(木)

歯磨きサポートプログラム -[shopping]

歯磨きをしている最中、「この部位 磨いたっけ?」と忘れてしまい、全部の歯を磨いたか不安になってしまうことがときどきあるので Windows のバッチファイル機能を使って「歯磨きサポートプログラム」を作成しました。

プログラムが 歯磨きする場所を「上の歯の奥」などと指示してくれるのでそれに従って歯磨きしていけば全部しっかり磨けます、というものです。

▼この動画は途中で音が鳴ります。

万一、使いたい方がいるなら下記の手順に従えばプログラムを体験できます。

今晩の歯磨きにいかがでしょうか。(冗談です)

  1. 歯磨き物語ver1.bat を右クリックして「名前を付けてリンク先を保存」等して、保存します。ファイル名はそのまま 歯磨き物語ver1.bat にしてください。
  2. 保存したら、そのファイルを…
    その前に注意事項:
    • このファイルは Windows に対していろいろ命令することが可能なファイル「バッチファイル」なので、何を行うファイルなのか事前に右クリックして「編集」を選び、中身を確認してください。(「編集」を選ぶと、下記手順3番と同じ画面が出るので3番と同じ操作をしてください)
    • 中身はプログラムなので、わかる人にしかわからない内容です。わからない人は残念ですがこのプログラムは実行しないでください。
    • 「このWebページの管理人は今までページを読んできて、だいたいこんなヤツだよ」と素性がわかる人は、まぁだいたい安心して実行してください。
    • ただし、その場合もこのWebページが何者かによって「かいざん」されていれば、プログラムの途中で format c:などと書いてあればディスクが壊れるので注意してください。(いかなる場合も私は責任を持てません)

    この注意事項を読んだら、ダブルクリックして実行します。

  3. もし、「Windows によって PC が保護されました」という画面が出たら、「詳細情報」をクリックし、表示される「実行」ボタンを押します。
  4. すると上の動画と同じ画面が表示されるので、画面の指示に従って歯磨きを始めてください。


ある程度カスタマイズできます。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/12(日)

新型コロナ -[health]

NHKの7/12(日)のニュースで、

これっていったいどうなってるの? ってかんじ…。

東京都で、4日間、200人、200人、200人、200人! 合計800人! これが初めてだと。

インフルエンザウイルスも、ワクチンがなかったらこうなってたってことかな…。(感染力の違いはあるけど)

ワクチンさえあれば、かな?

「ワクチンがない間は一切気を抜けません」ってことかな。それがそうだとすると、人類全員に周知させないといけないんじゃないかな。


(訪問者のどんなニーズと この記事がつながるか)


2020/7/3(金)

「RPG試作」 -[rpg]

最近このページの最初の表「NO PC WEEK に代わる PC 使用制限のしくみ(β版)」の右端に作業内容として「RPG試作」と書いています。

これはRPGのいろいろな動きについて部分的に作っているということで、その中でも特に「サブメニュー」システムについて試行錯誤を行っています。

たとえばドラゴンクエストはAボタンを押すとコマンドメニューが開いて、「しらべる」とか「どうぐ>どれを>つかう」とかウィンドウがいくつか開いて、やりたいことを実行できるあれです。

▼「ドラゴンクエストII」みたいなメニュー

このメニューの左から2番目「だれの?」の次のメニューが、「だれの?」で選んだキャラクターによって変化する(持ち物はキャラごとに異なる)、というのをシンプルにプログラムするにはどうすれば良いのか で悩んでいます。

メニューの内容が最初から静的に決め打ちできず、動的に変化するというのが難しい。

何も考えずにプログラムするなら、雑なプログラムでいくらでもそういうことはできると思いますが、

などなど、気にしながらプログラムしようとすると、簡単にはいきません。

「エレガントなプログラム」という言葉は、私が昔、高専の情報工学科に通っていたころに、プログラムの先生が使っていた言葉です。

そういうところでこそ、そういう言葉が使われるってことですね。

私が、中学から高校への進路として高専を選んだ理由は単に「パソコンが好きだから」というだけで、それ以外のことは何も考えていませんでした。

何も考えていなかったせいか、パソコンにおぼれた生活を送ってしまい、学業がうまく回らずに中退の道へ流れてしまいました。それはさておき…


エレガントなプログラムを求めた1つの例として…

「だれの?」というメニューに、「次のメニュー(道具のリスト)を作成するための手掛かりとなる情報」を付与しておく。

キャラクターの選択が行われたとき、そのメニューに付与情報があるなら、その情報をもとにサブメニュー(道具のリスト)を作る…

andChainToプロパティを追加する。(付与情報)

{                              //コマンドメニューの項目のひとつ「どうぐ」 のデータ構造。
    title : "どうぐ",   
    subMenu : {                //「どうぐ」は、サブメニューとして「だれの?」を表示
        title : "だれの?",
        items : this.chars,    //キャラクターの名前を項目として並べる
        andChainTo : "dougus", //付与情報 その選択の後のメニューの構築のための情報。
    },
},

「and chain to」は「~にチェーンします」という意味です。(そういう英語があるかどうかは知りません)

「キャラを選択して終わりではなく、続いてそのキャラの道具を選びます」という意味になります。

プログラムのおおまかな流れで、サブメニューを開くかどうかという部分は、「選んだ項目が、items というメンバを持っている場合、サブメニューを開く」となっています。

if( selectedItem.items ) {
    menu.subMenu = new Menu( ... );
}

(ここで言う item はメニューの「項目」という意味です。「道具」ではないです)

items として this.chars を指定し、キャラクターを選ぶメニューを表示することができます。

しかし、this.chars は items というメンバを持っていないので、そこでメニューは止まってしまいます。(キャラを選択して終わり)

「ならば、メニューのために別途、this.chars をコピーして新しい配列を作り、items を加えればいい」というやり方も考えられます。しかし今はちょっとシンプルとエレガントを求めていて、「コピーして新しい配列を作る」というのはあまりエレガントではないので採用できません。


Menu というプログラムの道具は「さまざまなメニューに使える」という汎用性を考えて作り始めました。

今回はその Menu に andChainTo という付与情報を加えることを考えました。

しかし、それが「Menu の本来の動きに必要のないもの」と(私によって)判断されることも将来的にはあります。

そう判断された場合、ゲームの中のちょっとした都合で使うというものは Menu の中には入れたくないので排除することになります。きびしく聞こえますが、これは私の個人的なこだわりではなく、Menu など「汎用的に」作ろうとするものがこの先プログラミングを続けていく中で、障害物になるかどうかに関わっていると思います。

まぁ、気楽に作りたいというときに、そういう難しい考え方はうるさく聞こえるので、やはり個人個人の考え方・やり方によるものだと思います。


いろいろ脱線しましたが、最近行っている「RPG試作」の内訳の話をしているところでした。

「サブメニュー」システムを作っていて、そのほか、 F キーを押すとフルスクリーンになるとか、ゲームパッドに対応しているとか…前にも日記に書いたかもしれませんが、そんなことをやっています。

▼フルスクリーンに対応

グラフィカルな、目を引くイケイケの画面は後回しです。


あと、大事なことだと思いますが、このページの最初の「NO PC WEEK に代わる PC 使用制限のしくみ(β版)」の表の実施により、私の日ごろのプログラミングの時間は、かつての10分の1(10%)くらいまで減っていますが、生産性(量ではなく質)が上がっています。


(訪問者のどんなニーズと この記事がつながるか)



webappsrcの確認

1. %%com.webapp.src:/webappsrccheck.html%%
と記述した場合

webapps/src/default.cssのスタイル指定が効く
<!DOCTYPE html><!--ESCAPEPROCESS-->

<head>

<script>

function onloadx() {

//一般関数

console.log( "文字列" );

}

function Class1() {

//クラス

console.log( "文字列" );

}

Class1.prototype.method1 = function() {

//メソッド

console.log( "文字列" );

}

</script>

</head>

<body onload="onloadx();" style="">

Hello world!<BR>

</body>

</html>



2. <code>
%%com.webapp.src:/webappsrccheck.html%%
</code>
と記述した場合

このファイルのcodeのスタイル指定が効く
<!DOCTYPE html><!--ESCAPEPROCESS-->

<head>

<script>

function onloadx() {

//一般関数

console.log( "文字列" );

}

function Class1() {

//クラス

console.log( "文字列" );

}

Class1.prototype.method1 = function() {

//メソッド

console.log( "文字列" );

}

</script>

</head>

<body onload="onloadx();" style="">

Hello world!<BR>

</body>

</html>



3.
%%com.webapp.src:/webappsrccheck2.html,/webappsrccheck.html%%
と記述した場合

webapps/src/default.cssのスタイル指定が効く
<!DOCTYPE html><!--ESCAPEPROCESS-->

<head>

<script>

function onloadx() {

//一般関数 コメント変更

console.log( "文字列変更" );

行追加

}

function Class1() {

//クラス コメント変更

console.log( "文字列変更" );

行追加

}

Class1.prototype.method1 = function() {

//メソッド コメント変更

console.log( "文字列変更" );

行追加

}

</script>

</head>

<body onload="onloadx();文字列変更" style="">

Hello world!<BR>

HTML追加

</body>

</html>



4. <code>
%%com.webapp.src:/webappsrccheck2.html,/webappsrccheck.html%%</code>
と記述した場合

このファイルのcodeのスタイル指定が効く
<!DOCTYPE html><!--ESCAPEPROCESS-->

<head>

<script>

function onloadx() {

//一般関数 コメント変更

console.log( "文字列変更" );

行追加

}

function Class1() {

//クラス コメント変更

console.log( "文字列変更" );

行追加

}

Class1.prototype.method1 = function() {

//メソッド コメント変更

console.log( "文字列変更" );

行追加

}

</script>

</head>

<body onload="onloadx();文字列変更" style="">

Hello world!<BR>

HTML追加

</body>

</html>



5. リンクで
src?webappsrccheck.html
と記述した場合

webapps/src/default.cssのスタイル指定が効く
開く

6. リンクで
src?webappsrccheck2.html,webappsrccheck.html
と記述した場合

webapps/src/default.cssのスタイル指定が効く
開く